using System.Collections.Generic;
using System.Linq;
using Cinemachine;
using UnityEngine;

public class CameraShaker : MonoBehaviour
{
    
    [SerializeField]
    private float _shakeDecreaseAmount = 10f;// 震动幅度减少的速率，每秒减少的幅度

    private readonly List<ShakeRequest> _requests = new List<ShakeRequest>(); // 用于存储震动请求的列表

    private CinemachineBasicMultiChannelPerlin _noise; // CinemachineBasicMultiChannelPerlin组件，用于控制相机震动效果


    private void Awake()
    {
        // 获取CinemachineBasicMultiChannelPerlin组件
        _noise = GetComponent<CinemachineVirtualCamera>()
            .GetCinemachineComponent<CinemachineBasicMultiChannelPerlin>();
    }

    private void Update()
    {
        if (_requests.Count == 0)
        {
            _noise.m_AmplitudeGain = 0; // 如果没有震动请求，将AmplitudeGain设置为0，停止震动效果
            return;
        }
        var strongestShake = _requests.Max(shake => shake.ShakeAmount); // 获取最强烈的震动请求
        _noise.m_AmplitudeGain = strongestShake; // 将AmplitudeGain设置为最强烈的震动请求的幅度

        // 遍历所有的震动请求
        for (var i = _requests.Count - 1; i >= 0; i--)
        {
            var request = _requests[i];

            // 减少震动请求的持续时间
            request.ShakeTime -= Time.deltaTime;

            // 如果震动请求的持续时间小于等于0，开始减少震动幅度
            if (request.ShakeTime <= 0)
            {
                request.ShakeAmount = Mathf.Max(0, request.ShakeAmount - Time.deltaTime * _shakeDecreaseAmount);
            }

            // 如果震动幅度已经减少到0，从列表中移除该震动请求
            if (request.ShakeAmount == 0) _requests.Remove(request);
        }
    }

    // 请求相机震动，指定震动的幅度和持续时间
    public void RequestShake(float amount, float time)
    {
        _requests.Add(new ShakeRequest // 向列表中添加一个新的ShakeRequest
        {
            ShakeAmount = amount, // 震动的幅度
            ShakeTime = time // 震动的持续时间
        });
    }

    // 震动请求类，用于存储一个震动请求的幅度和持续时间
    private class ShakeRequest
    {
        public float ShakeAmount { get; set; } // 请求的震动幅度
        public float ShakeTime { get; set; } // 请求的震动持续时间
    }
}
